<template>
  <el-dialog
    :title="exportConfig.title"
    :visible.sync="dialogOption.visible"
    :append-to-body="true"
    width="500px"
    v-dialogDrag
  >
    <div class="dialog_content">
      <el-form ref="form" label-width="100px">
        <el-form-item label="文件名">
          <el-input v-model="exportForm.filename" style="width: 100%" clearable>
          </el-input>
        </el-form-item>
        <el-form-item label="保存类型">
          <el-select v-model="exportForm.type" style="width: 100%">
            <el-option
              v-for="(item, index) in typeList"
              :key="index"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="要导出的数据">
          <el-select v-model="exportForm.mode" style="width: 100%">
            <el-option
              v-for="(item, index) in modeList"
              :key="index"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="要导出的字段" style="margin-bottom: 0px">
          <div class="el-card__header" style="padding-left: 0px">
            <el-checkbox
              :indeterminate="isIndeterminate"
              v-model="checkAll"
              @change="handleCheckAllChange"
              >全选
            </el-checkbox>
          </div>
          <el-checkbox-group
            v-model="exportForm.columns"
            @change="handleCheckedCitiesChange"
            style="max-height: 200px; display: grid; overflow: auto"
          >
            <el-checkbox
              v-for="(item, index) in columns"
              :label="item"
              :key="index"
              @change="checkChange($event, item)"
              >{{ item.name || item.label }}
            </el-checkbox>
          </el-checkbox-group>
        </el-form-item>
      </el-form>
    </div>
    <div slot="footer" class="dialog-footer">
      <!-- <el-button @click="printEvent()">打印</el-button> -->
      <el-button type="primary" @click="exportEvent()">导出</el-button>
    </div>
  </el-dialog>
</template>
<script>
import poiApi from "@common/api/poiApi";
import common from "@common/api/common";
import constants from "@common/api/constants";
import XEUtils from "xe-utils";

var defaultHtmlStyle =
  'body{margin:0;color:#333333}body *{-webkit-box-sizing:border-box;box-sizing:border-box}.vxe-table{border:0;border-collapse:separate;text-align:left;font-size:14px;border-spacing:0}.vxe-table:not(.is--print){table-layout:fixed}.vxe-table.is--print{width:100%}.vxe-table.border--default,.vxe-table.border--full,.vxe-table.border--outer{border-top:1px solid #e8eaec}.vxe-table.border--default,.vxe-table.border--full,.vxe-table.border--outer{border-left:1px solid #e8eaec}.vxe-table.border--outer,.vxe-table.border--default th,.vxe-table.border--default td,.vxe-table.border--full th,.vxe-table.border--full td,.vxe-table.border--outer th,.vxe-table.border--inner th,.vxe-table.border--inner td{border-bottom:1px solid #e8eaec}.vxe-table.border--default,.vxe-table.border--outer,.vxe-table.border--full th,.vxe-table.border--full td{border-right:1px solid #e8eaec}.vxe-table.border--default th,.vxe-table.border--full th,.vxe-table.border--outer th{background-color:#f8f8f9}.vxe-table td>div,.vxe-table th>div{padding:.5em .4em}.col--center{text-align:center}.col--right{text-align:right}.vxe-table:not(.is--print) .col--ellipsis>div{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-break:break-all}.vxe-table--tree-node{text-align:left}.vxe-table--tree-node-wrapper{position:relative}.vxe-table--tree-icon-wrapper{position:absolute;top:50%;width:1em;height:1em;text-align:center;-webkit-transform:translateY(-50%);transform:translateY(-50%);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer}.vxe-table--tree-unfold-icon,.vxe-table--tree-fold-icon{position:absolute;width:0;height:0;border-style:solid;border-width:.5em;border-right-color:transparent;border-bottom-color:transparent;}.vxe-table--tree-unfold-icon{left:.3em;top:0;border-left-color:#939599;border-top-color:transparent;}.vxe-table--tree-fold-icon{left:0;top:.3em;border-left-color:transparent;border-top-color:#939599;}.vxe-table--tree-cell{display:block;padding-left:1.5em}.vxe-table input[type="checkbox"]{margin:0}.vxe-table input[type="checkbox"],.vxe-table input[type="radio"],.vxe-table input[type="checkbox"]+span,.vxe-table input[type="radio"]+span{vertical-align:middle;padding-left:0.4em}';
var csvBOM = "\uFEFF";
var enterSymbol = "\r\n";
function toTxtCellLabel(val) {
  if (/[",]/.test(val)) {
    return '"'.concat(val.replace(/"/g, '""'), '"');
  }
  return val || "";
}
function getCsvCellTypeLabel(column, cellValue) {
  if (cellValue) {
    switch (column.cellType) {
      case "string":
        if (!isNaN(cellValue)) {
          return "\t" + cellValue;
        }
        break;
      case "number":
        break;
      default:
        if (cellValue.length >= 12 && !isNaN(cellValue)) {
          return "\t" + cellValue;
        }
        break;
    }
  }
  return cellValue;
}
function getHeaderTitle(opts, column) {
  return (
    (opts.original ? column.name || column.label : column.getTitle()) || ""
  );
}
function getCellTitle(row, opts, column) {
  return XEUtils._getCellValue(row, column, opts.convert);
}
export default {
  name: "export",
  components: {},
  props: {
    tableOptions: Object,
  },
  watch: {},

  data() {
    return {
      checkAll: false,
      isIndeterminate: true,
      dialogOption: {
      visible: false,
      // title: '导出参数配置',
      },
      exportForm: {
        filename: "", //文件名
        type: "xlsx", //文件类型
        mode: "all", //导出的数据
        columns: [],
      },
      typeList: [
        { label: "Excel(*.xlsx)", value: "xlsx" },
        { label: "CSV (逗号分隔)(*.csv)", value: "csv" },
        { label: "网页(*.html)", value: "html" },
        { label: "XML 数据(*.xml)", value: "xml" },
        { label: "文本文件(制表符分隔)(*.txt)", value: "txt" },
      ],
      modeList: [
        { label: "当前数据（当前页的数据）", value: "current" },
        { label: "全部数据（不分页的数据）", value: "all" },
        // { label: "选中数据（当前页选中的数据）", value: "selected" },
      ],
    };
  },
  created() {},
  methods: {
    checkChange($event, item) {},
    handleCheckAllChange(val) {
      this.exportForm.columns = val
        ? this.columns.map((item) => {
            return item;
          })
        : [];
      this.isIndeterminate = false;
    },
    handleCheckedCitiesChange(value) {
      let checkedCount = value.length;
      this.checkAll = checkedCount === this.columns.length;
      this.isIndeterminate =
        checkedCount > 0 && checkedCount < this.columns.length;
    },
    showEvent: function showEvent($table, options) {
      this.handleCheckAllChange(true);
      this.checkAll = true;
      this.exportForm.filename = "";
      this.exportForm.filename =
        this.exportConfig.filename +
        "_" +
        this.$utils.formatDate(new Date(), "yyyy-MM-dd");
      if (this.exportConfig.showDialog) {
        this.dialogOption.visible = true;
      } else {
        if (this.exportConfig.isPrint) {
          this.printEvent(options);
        } else {
          this.exportEvent(options);
        }
      }
    },
    cancelEvent: function cancelEvent() {
      this.dialogOption.visible = false;
    },
    async getOpts(options) {
      let $this = this;
      let $table = this.table;
      var opts = Object.assign(
        {
          isHeader: true,
          isColgroup: true,
          download: true,
          original: true,
          type: "csv",
          mode: "current",
        },
        {
          print: false,
        },
        options || {},
        this.exportForm
      );
      var type = opts.type,
        mode = opts.mode,
        columns = opts.columns;
      let groups = [];
      groups = this.$XEUtils.searchTree(
        columns,
        (column, index) => column.visible != false,
        { children: "children", mapChildren: "childNodes", original: true }
      );
      // 获取所有列
      const cols = [];
      this.$XEUtils.eachTree(
        groups,
        (column) => {
          const isColGroup = column.children && column.children.length;
          if (!isColGroup) {
            cols.push(column);
          }
        },
        { children: "childNodes" }
      );
      // 构建分组层级
      opts.columns = cols;
      opts.colgroups = this.$XEUtils.convertToRows(groups);

      if (!opts.filename) {
        opts.filename =
          $this.exportForm.filename ||
          $this.exportConfig.filename +
            "_" +
            this.$utils.formatDate(new Date(), "yyyy-MM-dd");
      }
      if (!opts.sheetName) {
        opts.sheetName = document.title;
      } // 检查类型
      if (!opts.data) {
        if (mode === "selected") {
          opts.data = $table.selection;
        } else if (mode === "current") {
          opts.data = $table.data;
        } else if (mode === "all") {
          opts.data = await this.getAllDataExcel(opts);
        }
      }
      return opts;
    },
    async printEvent(options) {
      let $this = this;
      let $table = this.table;
      var opts = await this.getOpts(options);
      var html = this.toHtml($table, opts, opts.columns, opts.data);
      let printConfig = Object.assign({}, this.tableOptions.printConfig);
      this.cancelEvent();
      this.$XPrint({ ...printConfig, content: html });
    },

    async exportEvent(options) {
      let $this = this;
      let $table = this.table;
      var opts = await this.getOpts(options);
      this.downloadFile(
        $table,
        opts,
        await this.getContent($table, opts, opts.columns, opts.data)
      );
      this.cancelEvent();
    },
    getExportOption() {
      const columns = XEUtils.searchTree(
        this.columns,
        (column) => column.checked,
        {
          children: "children",
          mapChildren: "childNodes",
          original: true,
        }
      );
      return Object.assign({ columns });
    },
    createHtmlPage(opts, content) {
      var style = opts.style;
      return [
        "<!DOCTYPE html><html>",
        "<head>",
        '<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui">',
        "<title>".concat(opts.sheetName, "</title>"),
        "<style>".concat(defaultHtmlStyle, "</style>"),
        style ? "<style>".concat(style, "</style>") : "",
        "</head>",
        "<body>".concat(content, "</body>"),
        "</html>",
      ].join("");
    },
    toCsv($table, opts, columns, datas) {
      var content = csvBOM;
      if (opts.isHeader) {
        content +=
          columns
            .map(function (column) {
              return toTxtCellLabel(getHeaderTitle(opts, column)) + "\t";
            })
            .join(",") + enterSymbol;
      }

      datas.forEach(function (row) {
        content +=
          columns
            .map(function (column) {
              return (
                toTxtCellLabel(
                  getCsvCellTypeLabel(column, getCellTitle(row, opts, column))
                ) + "\t"
              );
            })
            .join(",") + enterSymbol;
      });

      return content;
    },
    toTxt($table, opts, columns, datas) {
      var content = "";

      if (opts.isHeader) {
        content +=
          columns
            .map(function (column) {
              return toTxtCellLabel(getHeaderTitle(opts, column));
            })
            .join("\t") + enterSymbol;
      }

      datas.forEach(function (row) {
        content +=
          columns
            .map(function (column) {
              return toTxtCellLabel(getCellTitle(row, opts, column));
            })
            .join("\t") + enterSymbol;
      });
      return content;
    },

    toHtml($table, opts, columns, datas) {
      var isPrint = opts.isPrint,
        isHeader = opts.isHeader;
      var tables = this.$XEUtils.jsonToTable(
        columns,
        datas,
        this.exportConfig.convert
      );
      return isPrint ? tables : this.createHtmlPage(opts, tables);
    },

    toXML($table, opts, columns, datas) {
      var xml = [
        '<?xml version="1.0"?>',
        '<?mso-application progid="Excel.Sheet"?>',
        '<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">',
        '<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">',
        "<Version>16.00</Version>",
        "</DocumentProperties>",
        '<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">',
        "<WindowHeight>7920</WindowHeight>",
        "<WindowWidth>21570</WindowWidth>",
        "<WindowTopX>32767</WindowTopX>",
        "<WindowTopY>32767</WindowTopY>",
        "<ProtectStructure>False</ProtectStructure>",
        "<ProtectWindows>False</ProtectWindows>",
        "</ExcelWorkbook>",
        '<Worksheet ss:Name="'.concat(opts.sheetName, '">'),
        "<Table>",
        columns
          .map(function (column) {
            return '<Column ss:Width="'.concat(column.realWidth, '"/>');
          })
          .join(""),
      ].join("");

      if (opts.isHeader) {
        xml += "<Row>".concat(
          columns
            .map(function (column) {
              return '<Cell><Data ss:Type="String">'.concat(
                getHeaderTitle(opts, column),
                "</Data></Cell>"
              );
            })
            .join(""),
          "</Row>"
        );
      }

      datas.forEach(function (row) {
        xml +=
          "<Row>" +
          columns
            .map(function (column) {
              return `<Cell><Data ss:Type="String">${toTxtCellLabel(
                row[column.property]
              )} </Data></Cell>`;
            })
            .join("") +
          "</Row>";
      });
      return "".concat(xml, "</Table></Worksheet></Workbook>");
    },
    async toXlsx($table, opts, columns, datas) {
      columns = columns.map((item) => {
        return {
          name: item.label,
          key: item.key || item.prop,
          format: item.format,
            type: item.exportType,
        };
      });
      columns =[{name: '序号', key: '_index', width: 10, type: 10}].concat(columns)
      let _export = [
        columns,
        this.exportConfig.url,
        this.exportConfig.queryData || "",
        this.exportConfig.filename,
        this.exportConfig.convert,
      ];

      switch (opts.mode) {
        case "current":
          _export.push(this.tableOptions.pagination.pageIndex);
          _export.push(this.tableOptions.pagination.pageSize);
        case "all":
        case "selected":
          if (typeof _export[2] == "object") {
            let id_list = this.table.selection.map((item) => item.id);
            _export[2].id_list = id_list;
          }
      }
      let content = await this.exportExcel(..._export);//yuan

      //   opts.subData =Object.assign({},{
      //   title_field:columns,
      //   url:poiApi.getFullUrl(this.exportConfig.url),
      //   params:this.exportConfig.queryData || "",
      //   output_name:this.exportConfig.filename,
      //   convert:this.exportConfig.convert,
      //   },opts.subData);
      // switch (opts.mode) {
      //   case "current":
      //     opts.subData.pageNo = this.tableOptions.pagination.pageIndex;
      //     opts.subData.pageSize = this.tableOptions.pagination.pageSize;
      //   case "all":
      //   case "selected":
      // }
      //   console.log(' opts.subData', opts.subData)
      //   console.log(' opts.subData', opts,)

      // let content = await this.exportExcelTemplate(opts.subData);
      console.log("content", content, this.columns);
      return content;
    },

    getContent($table, opts, columns, datas) {
      if (columns.length) {
        switch (opts.type) {
          case "xlsx":
            return this.toXlsx($table, opts, columns, datas);
          case "csv":
            return this.toCsv($table, opts, columns, datas);
          case "txt":
            return this.toTxt($table, opts, columns, datas);
          case "html":
            return this.toHtml($table, opts, columns, datas);
          case "xml":
            return this.toXML($table, opts, columns, datas);
        }
      }
      return "";
    },
    downloadFile($table, opts, content) {
      var filename = opts.filename,
        type = opts.type,
        download = opts.download;
      if (!download) {
        var blob = this.$XEUtils.getExportBlobByContent(content, opts);
        return Promise.resolve({
          type: type,
          content: content,
          blob: blob,
        });
      }
      this.$XEUtils
        ._saveLocalFile({
          filename: filename,
          type: type,
          content: content,
        })
        .then(function () {
          if (opts.message !== false) {
            // this.$message.success(opts.message)
          }
        });
    },
    async exportExcel(
      title_field,
      url,
      params,
      output_name,
      convert,
      pageNo,
      pageSize
    ) {
      let subData = {
        title_field: JSON.stringify(title_field),
        url: poiApi.getFullUrl(url),
        params,
        output_name,
        convert,
        pageNo,
        pageSize,
      };
      if (!this.$utils.isNotEmpty(title_field)) {
        this.$message.error("模板定义不能为空");
        return;
      }
      if (!this.$utils.isNotEmpty(url)) {
        this.$message.error("请求路径不能为空");
        return;
      }
      if (!this.$utils.isNotEmpty(params)) {
        this.$message.error("请求参数不能为空");
        return;
      }
      if (!this.$utils.isNotEmpty(output_name)) {
        this.$message.error("文件名称不能为空");
        return;
      }
      let $this = this;
      let content;
      await common.exportData(
        constants.API_ExportExcel,
        subData,
        {
          responseType: "arraybuffer",
        },
        (res) => {
          res = this.$XEUtils.getExportBlobByContent(res, {
            type: "application/json",
          });
          content = res;
        }
      );

      return content;
    },
    async exportExcelTemplate(opts){
        let subData = {
            template_name:opts.template_name,
            url: opts.url,
            params:opts.params,
            output_name:opts.output_name,
            convert:opts.convert,
            pic_field:opts.pic_field,
            pageNo:opts.pageNo,
            pageSize:opts.pageSize,
            title_field: JSON.stringify(opts.title_field),
        };
        subData = subData

        console.log('Api_url',subData,opts)
        if (!this.utils.isNotEmpty(opts.template_name)) {
            this.message.error('模板名称不能为空');
            return;
        }
        if (!this.utils.isNotEmpty(opts.url)) {
            this.message.error('请求路径不能为空');
            return;
        }
        if (!this.utils.isNotEmpty(opts.params)) {
            this.message.error('请求参数不能为空');
            return;
        }
        if (!this.utils.isNotEmpty(opts.output_name)) {
            this.message.error('文件名称不能为空');
            return;
        }
        let content;
        // let Api_url = subData.template_name?constants.API_ExportExcelTemplate:constants.API_ExportExcel
        // await common.exportData(Api_url, subData, {
        //     responseType: 'arraybuffer'
        // }, res => {
        //    res = this.$XEUtils.getExportBlobByContent(res, {
        //     type: "application/json",
        //   });
        //   content = res;
        // }
      // );
      return content;
    },
    async getAllDataExcel(opts) {
      let $this = this;
      let content = "";
      await common.requestData(
        this.exportConfig.url,
        { ...this.exportConfig.queryData, nopage: "1" },
        (res) => {
          content = res.data;
        }
      );
      return content;
    },
  },
  computed: {
    table() {
      return this.$parent.$refs[this.tableOptions.ref];
    },
    exportConfig() {
      return this.tableOptions.exportConfig || {};
    },
    columns() {
      let arr = ["_index", "_section", "operates"];
      return (
        (this.table && this.tableOptions.columns) ||
        // this.table.store.states.columns.filter((item) => {
        //   item.name = item.label;
        //   item.property = item.key;
        //   return !arr.includes(item.property);
        // })
        []
      );
    },
  },
};
</script>
